/*****************************************************
** Author:
** Date: 2019-10-19
*
*****************************************************/

#include "method.h"




/**
 * @brief  array input and integer output
 * @param  None
 * @retval None
 */
int lua_arch_io_method1(lua_State *L, const char *function, \
                        unsigned char *input, int inlen, int *val)
{
    int type, err;

    // get lua function name
    type = lua_getglobal(L, function);
    lua_log_dbg("lua_getglobal '%s' type %d", function, type);
    // print_lua_stack(L);

    lua_arch_pushtable(L, input, inlen);

    err = lua_pcall(L, 1, 1, 0);
    lua_log_dbg("lua_pcall err %d", err);
    if (err != LUA_OK)
    {
        lua_log_err("lua_pcall failed %d", err);
        return -1;
    }

    if (val) {
        *val = lua_tointeger(L, -1);
        lua_log_dbg("%s return %d", function, *val);
    }
        // print_lua_stack(L);

    lua_pop(L, 1);
    lua_log_dbg("lua_pop %d done", 1);
    // print_lua_stack(L);
    return 0;
}

/*
 *  array input and array output
 */
int lua_arch_io_method2(lua_State *L, const char *function, \
                        unsigned char *input, int inlen, \
                        unsigned char *output, int maxsize, int *outlen)
{
    int i, type, err;

    // get lua function name
    type = lua_getglobal(L, function);
    lua_log_dbg("lua_getglobal '%s' type %d", function, type);

    lua_arch_pushtable(L, input, inlen);

    err = lua_pcall(L, 1, 1, 0);
    if (err != LUA_OK)
    {
        lua_log_err("lua_pcall failed %d", err);
        return -1;
    }
    // print_lua_stack(L);

    // skip table[0] which is invalid
    for (i = 1; (type = lua_rawgeti(L, -1, i)) != 0; ++i)
    {
        // print_lua_stack(L);
        lua_log_dbg("echo_data index %d type %s return %d", \
                    i, lua_typename(L, type), lua_tointeger(L, -1));
        output[i-1] = lua_tointeger(L, -1);
        lua_pop(L, 1);
    }

    // remove array[0]
    if (outlen)
        *outlen = i - 1;

    lua_pop(L, -1); // cleanup stack
    return 0;
}

/*
 *  array input and string output
 */
int lua_arch_io_method3(lua_State *L, const char *function, \
                        unsigned char *input, int inlen, \
                        unsigned char *outstr, int maxsize)
{
    int type, err, strsize;
    char *luastr;

    /* get the domain function from lua file. */
    type = lua_getglobal(L, function);
    lua_log_dbg("lua_getglobal '%s' type %d", function, type);

    lua_arch_pushtable(L, input, inlen);

    /* exec the domain function. */
    err = lua_pcall(L, 1, 1, 0);
    lua_log_dbg("lua_pcall err %d", err);
    if (err != LUA_OK)
    {
        lua_log_err("lua_pcall failed %d", err);
        return -1;
    }
    luastr = (char *)lua_tostring(L, -1);
    lua_log_dbg("%s", luastr);
    if ((strsize = strlen(luastr)) >= maxsize)
        return -1;

    lua_log_dbg("strsize %d", strsize);
    strcpy((char *)outstr, luastr);
    outstr[strsize] = '\0';

    lua_pop(L, 1);
    lua_log_dbg("lua_pop %d done", 1);
    return 0;
}

/*
 *  integer and array input, integer output
 */
int lua_arch_io_method4(lua_State *L, const char *function, \
                        int val1, int val2)
{
    int type, err, ret;

    /* get the domain function from lua file. */
    type = lua_getglobal(L, function);
    lua_log_dbg("lua_getglobal '%s' type %d", function, type);

    lua_pushinteger(L, val1);
    lua_pushinteger(L, val2);

    /* exec the domain function. */
    err = lua_pcall(L, 2, 1, 0);
    if (err != LUA_OK)
    {
        lua_log_err("lua_pcall failed %d:%s", err, lua_tostring(L, -1));
        return -1;
    }

    switch (type = lua_type(L, -1)) {
        case LUA_TNUMBER:
        ret = lua_tointeger(L, -1);
        lua_log_dbg("%d", ret);
        break;
        return -3;
        default:
        lua_log_err("method4 unkown type %s", lua_typename(L, type));
        return -3;
    }

    lua_pop(L, 1);
    lua_log_dbg("lua_pop %d done", 1);
    return 0;
}

int lua_arch_method_data2kv(lua_State *L, const char *function, \
                            int cloudid, unsigned char *input, int inlen, \
                            unsigned char *snapshot, int snapsize, \
                            unsigned char *kv, int maxsize)
{
    if (lua_getglobal(L, function) != LUA_TFUNCTION)
        return -1;

    lua_pushinteger(L, cloudid);
    lua_arch_pushtable(L, input, inlen);
    lua_arch_pushtable(L, snapshot, snapsize);
    // print_lua_stack(L);

    int err = lua_pcall(L, 3, 1, 0);
    lua_log_dbg("lua_pcall err %d", err);
    if (err != LUA_OK)
    {
        lua_log_err("lua_pcall failed %d", err);
        return -2;
    }
    // print_lua_stack(L);

    int strsize;
    char *luastr = (char *)lua_tostring(L, -1);
    lua_log_dbg("%s", luastr);
    if ((strsize = strlen(luastr)) >= maxsize)
        return -3;

    lua_log_dbg("strsize %d", strsize);
    strcpy((char *)kv, luastr);
    kv[strsize] = '\0';

    // print_lua_stack(L);
    lua_pop(L, 1);
    lua_log_dbg("lua_pop %d done", 1);
    return 0;
}

int lua_arch_method_kve2data(lua_State *L, const char *function, \
                            int cloudid, unsigned char *input, int inlen, \
                            unsigned char *snapshot, int snapsize, \
                            unsigned char *output, int maxsize, int *outlen)
{
    if (lua_getglobal(L, function) != LUA_TFUNCTION)
        return -1;

    lua_pushinteger(L, cloudid);
    lua_arch_pushtable(L, input, inlen);
    lua_arch_pushtable(L, snapshot, snapsize);
    // print_lua_stack(L);

    int err = lua_pcall(L, 3, 1, 0);
    lua_log_dbg("lua_pcall err %d", err);
    if (err != LUA_OK)
    {
        lua_log_err("lua_pcall failed %d", err);
        return -2;
    }
    // print_lua_stack(L);

    int i, type;
    // skip table[0] which is nil
    for (i = 1; (type = lua_rawgeti(L, -1, i)) != 0; ++i)
    {
        // lua_log_dbg("[%d] type %s return %d", i, lua_typename(L, type), lua_tointeger(L, -1));
        if (type != LUA_TNUMBER)
            return -3;

        output[i-1] = lua_tointeger(L, -1);
        lua_pop(L, 1);
        // print_lua_stack(L);
    }

    // remove array[0]
    if (outlen)
        *outlen = i - 1;

    // print_lua_stack(L);
    lua_pop(L, -1);
    lua_log_dbg("clear stack done");
    return 0;
}

/* End of file */



